import CryptoJS from 'crypto-js';

// 讯飞语音识别服务
export class VoiceRecognitionService {
    private ws: WebSocket | null = null;
    private isRecording = false;
    private audioContext: AudioContext | null = null;
    private processor: ScriptProcessorNode | null = null;
    private stream: MediaStream | null = null;
    private processingTimeout?: number;
    // 标记是否由客户端主动关闭（正常业务流程），用于抑制关闭提示
    private closedByClient = false;

    // 讯飞API配置
    private readonly APPID = '4aa4d386';
    private readonly APISecret = 'YTMzNDcxNWRhODY4ZTY0ODczNDRmYmE2';
    private readonly APIKey = '3a1d98049a35594c5b7f8065d8d392e1';
    private readonly wsUrl = 'wss://iat-api.xfyun.cn/v2/iat';

    // 回调函数
    private onResult?: (text: string) => void;
    private onError?: (error: string) => void;
    private onStatusChange?: (status: 'idle' | 'recording' | 'processing') => void;

    constructor() {
        console.log('讯飞语音识别服务初始化');
    }

    // 开始录音
    async startRecording(
        onResult: (text: string) => void,
        onError: (error: string) => void,
        onStatusChange: (status: 'idle' | 'recording' | 'processing') => void
    ) {
        this.onResult = onResult;
        this.onError = onError;
        this.onStatusChange = onStatusChange;

        try {
            // 建立WebSocket连接
            await this.ensureWebSocketConnection();

            // 获取麦克风权限
            const stream = await navigator.mediaDevices.getUserMedia({
                audio: {
                    sampleRate: 16000,
                    channelCount: 1,
                    echoCancellation: true,
                    noiseSuppression: true
                }
            });

            // 创建AudioContext处理音频
            const audioContext = new AudioContext({ sampleRate: 16000 });
            const source = audioContext.createMediaStreamSource(stream);
            const processor = audioContext.createScriptProcessor(4096, 1, 1);

            this.audioContext = audioContext;
            this.processor = processor;
            this.stream = stream;
            this.isRecording = true;
            this.onStatusChange?.('recording');

            processor.onaudioprocess = (event) => {
                if (!this.isRecording) return;

                const inputBuffer = event.inputBuffer;
                const inputData = inputBuffer.getChannelData(0);

                // 转换为16位PCM数据
                const pcmData = new Int16Array(inputData.length);
                for (let i = 0; i < inputData.length; i++) {
                    pcmData[i] = Math.max(-32768, Math.min(32767, inputData[i] * 32768));
                }

                // 发送PCM数据
                this.sendPCMData(pcmData);
            };

            source.connect(processor);
            processor.connect(audioContext.destination);

            console.log('开始录音');
        } catch (error) {
            console.error('开始录音失败:', error);
            this.onError?.('无法访问麦克风，请检查权限设置');
        }
    }

    // 停止录音
    stopRecording() {
        if (this.isRecording) {
            this.isRecording = false;

            // 延迟发送结束帧
            setTimeout(() => {
                this.sendEndFrame();
                this.onStatusChange?.('processing');

                // 设置处理超时
                this.processingTimeout = setTimeout(() => {
                    console.log('语音识别处理超时，重置状态');
                    this.onStatusChange?.('idle');
                    this.onError?.('语音识别超时，请重试');
                }, 10000);
            }, 200);

            // 清理音频资源
            this.cleanupAudioResources();
            console.log('停止录音');
        }
    }

    // 确保WebSocket连接
    private async ensureWebSocketConnection(): Promise<void> {
        return new Promise((resolve, reject) => {
            if (this.ws && this.ws.readyState === WebSocket.OPEN) {
                // 复用已连接的会话，但需要发送新的开始帧以开启新一轮识别
                console.log('WebSocket已连接，复用连接并发送新的开始帧');
                try {
                    this.sendStartFrame();
                    resolve();
                    return;
                } catch {
                    console.warn('复用连接发送开始帧失败，尝试重建连接');
                }
            }

            // 关闭现有连接
            if (this.ws) {
                this.ws.close();
                this.ws = null;
            }

            try {
                const authParams = this.generateAuthParams();
                const wsUrlWithAuth = `${this.wsUrl}?${authParams}`;

                console.log('尝试连接WebSocket:', wsUrlWithAuth);

                this.ws = new WebSocket(wsUrlWithAuth);

                // 设置连接超时
                const connectionTimeout = setTimeout(() => {
                    if (this.ws && this.ws.readyState !== WebSocket.OPEN) {
                        console.error('WebSocket连接超时');
                        this.ws.close();
                        reject(new Error('WebSocket连接超时'));
                    }
                }, 10000); // 10秒超时

                this.ws.onopen = () => {
                    clearTimeout(connectionTimeout);
                    console.log('讯飞语音识别WebSocket连接已建立');
                    this.sendStartFrame();
                    resolve();
                };

                this.ws.onmessage = (event) => {
                    this.handleWebSocketMessage(event);
                };

                this.ws.onerror = (error) => {
                    clearTimeout(connectionTimeout);
                    console.error('WebSocket错误:', error);
                    const errorMsg = 'WebSocket连接错误，请检查网络连接和API配置';
                    this.onError?.(errorMsg);
                    reject(new Error(errorMsg));
                };

                this.ws.onclose = (event) => {
                    clearTimeout(connectionTimeout);
                    console.log('WebSocket连接已关闭，代码:', event.code, '原因:', event.reason);

                    let errorMsg = 'WebSocket连接关闭';
                    if (event.code === 1006) {
                        errorMsg = 'WebSocket连接异常关闭，可能是认证失败或网络问题';
                    } else if (event.code === 1002) {
                        errorMsg = 'WebSocket协议错误，可能是认证参数错误';
                    } else if (event.code === 1003) {
                        errorMsg = 'WebSocket数据类型错误';
                    } else if (event.code === 1000 || event.code === 1005 || event.wasClean || this.closedByClient) {
                        // 1000 正常关闭 / 1005 无状态码（多数浏览器本地关闭时出现）/ wasClean=true / 客户端主动关闭
                        console.log('WebSocket正常关闭（抑制提示）');
                        this.closedByClient = false; // 重置标记
                        if (this.processingTimeout) {
                            clearTimeout(this.processingTimeout);
                            this.processingTimeout = undefined;
                        }
                        return;
                    } else if (event.code === 1001) {
                        errorMsg = 'WebSocket端点离开，可能是服务器重启';
                    } else if (event.code === 1011) {
                        errorMsg = 'WebSocket服务器错误';
                    }

                    console.error('WebSocket关闭详情:', {
                        code: event.code,
                        reason: event.reason,
                        wasClean: event.wasClean,
                        errorMsg
                    });

                    if (this.processingTimeout) {
                        clearTimeout(this.processingTimeout);
                        this.processingTimeout = undefined;
                    }
                    this.onError?.(errorMsg);
                    reject(new Error(`${errorMsg}: ${event.code} - ${event.reason}`));
                };
            } catch (error) {
                console.error('设置WebSocket失败:', error);
                const errorMsg = '设置WebSocket失败，请检查网络连接';
                this.onError?.(errorMsg);
                reject(new Error(errorMsg));
            }
        });
    }

    // 生成鉴权参数
    private generateAuthParams(): string {
        const now = new Date();
        const date = now.toUTCString();

        // 生成签名原始字符串
        const signatureOrigin = `host: iat-api.xfyun.cn\ndate: ${date}\nGET /v2/iat HTTP/1.1`;

        // 生成HMAC-SHA256签名
        const signatureSha = this.hmacSha256(signatureOrigin, this.APISecret);
        const signature = signatureSha;

        // 生成authorization
        const authorizationOrigin = `api_key="${this.APIKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${signature}"`;
        const authorization = btoa(authorizationOrigin);

        const authParams = `authorization=${authorization}&date=${encodeURIComponent(date)}&host=iat-api.xfyun.cn`;

        console.log('鉴权参数调试:', {
            date,
            signatureOrigin,
            signature,
            authorization,
            authParams,
            apiKey: this.APIKey,
            apiSecret: this.APISecret.substring(0, 10) + '...'
        });

        return authParams;
    }

    // HMAC-SHA256签名
    private hmacSha256(data: string, key: string): string {
        const hash = CryptoJS.HmacSHA256(data, key);
        return hash.toString(CryptoJS.enc.Base64);
    }

    // 发送开始帧
    private sendStartFrame() {
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;

        const startFrame = {
            common: {
                app_id: this.APPID
            },
            business: {
                language: "zh_cn",
                domain: "iat",
                accent: "mandarin",
                vad_eos: 10000
            },
            data: {
                status: 0,
                format: "audio/L16;rate=16000",
                encoding: "raw",
                audio: ""
            }
        };

        this.ws.send(JSON.stringify(startFrame));
        console.log('发送开始帧:', startFrame);
    }

    // 发送PCM数据
    private sendPCMData(pcmData: Int16Array) {
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
            console.log('WebSocket未连接，跳过发送音频数据');
            return;
        }

        try {
            // 将PCM数据转换为base64
            const base64Audio = btoa(String.fromCharCode(...new Uint8Array(pcmData.buffer)));

            const dataFrame = {
                data: {
                    status: 1,
                    format: "audio/L16;rate=16000",
                    encoding: "raw",
                    audio: base64Audio
                }
            };

            this.ws.send(JSON.stringify(dataFrame));
        } catch (error) {
            console.error('发送PCM数据失败:', error);
        }
    }

    // 发送结束帧
    private sendEndFrame() {
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;

        const endFrame = {
            data: {
                status: 2,
                format: "audio/L16;rate=16000",
                encoding: "raw",
                audio: ""
            }
        };

        this.ws.send(JSON.stringify(endFrame));
        console.log('发送结束帧:', endFrame);
    }

    // 处理WebSocket消息
    private handleWebSocketMessage(event: MessageEvent) {
        try {
            const response = JSON.parse(event.data);
            console.log('🔍 收到讯飞响应:', response);
            console.log('🔍 响应类型:', typeof response);
            console.log('🔍 响应代码:', response.code);
            console.log('🔍 响应数据:', response.data);

            if (response.code !== 0) {
                console.error('讯飞API错误:', response.message);
                this.onError?.(response.message || '识别失败');
                return;
            }

            if (response.data && response.data.result) {
                const result = response.data.result;
                console.log('🔍 识别结果数据:', result);
                let text = '';

                if (result.ws) {
                    console.log('🔍 处理识别结果片段:', result.ws);
                    result.ws.forEach((ws: { cw?: Array<{ w: string }> }) => {
                        if (ws.cw) {
                            ws.cw.forEach((cw: { w: string }) => {
                                text += cw.w;
                            });
                        }
                    });
                }

                console.log('🔍 提取的文字:', text);
                if (text) {
                    if (this.processingTimeout) {
                        clearTimeout(this.processingTimeout);
                        this.processingTimeout = undefined;
                    }
                    console.log('✅ 识别到文字:', text);
                    this.onResult?.(text);
                } else {
                    console.log('⚠️ 没有提取到文字内容');
                }
            } else {
                console.log('⚠️ 响应中没有识别结果数据');
            }

            // 检查是否是最后一个数据包
            if (response.data && response.data.status === 2) {
                if (this.processingTimeout) {
                    clearTimeout(this.processingTimeout);
                    this.processingTimeout = undefined;
                }
                this.onStatusChange?.('idle');
                console.log('语音识别完成');
                // 关闭本次会话，避免下一轮复用旧连接导致协议状态混乱
                if (this.ws && this.ws.readyState === WebSocket.OPEN) {
                    try {
                        this.closedByClient = true;
                        this.ws.close();
                    } catch (e) {
                        console.warn('关闭会话时出现警告:', e);
                    }
                }
            }
        } catch (error) {
            console.error('解析讯飞响应失败:', error);
            this.onError?.('解析响应失败');
        }
    }

    // 清理音频资源
    private cleanupAudioResources() {
        if (this.processor) {
            this.processor.disconnect();
        }
        if (this.audioContext) {
            this.audioContext.close();
        }
        if (this.stream) {
            this.stream.getTracks().forEach(track => track.stop());
        }
    }

    // 断开连接
    disconnect() {
        if (this.ws) {
            this.ws.close();
            this.ws = null;
        }
        if (this.isRecording) {
            this.stopRecording();
        }
        this.cleanupAudioResources();
    }
}

// 创建单例实例
export const voiceRecognitionService = new VoiceRecognitionService();
